package com.campus.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.campus.common.CampusWall;
import com.campus.common.Result;
import com.campus.common.UserStatus;
import com.campus.entity.*;
import com.campus.mapper.UsersMapper;
import com.campus.service.UserService;
import com.campus.utils.MD5Util;
import com.campus.utils.SnowFlakeUtil;
import com.campus.utils.TokenUtils;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

import static com.campus.common.RedisCache.CAPTCHA_KEY;
import static com.campus.common.RedisCache.EMAIL_CODE_KEY;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UsersMapper usersMapper;
    @Autowired
    private TokenUtils tokenUtils;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    JavaMailSender javaMailSender;

    /**
     * 用户注册
     * @param
     * @return
     */
    public Result register(User user) {
        //查询用户
        //手动添加雪花id
        user.setUserId(SnowFlakeUtil.getId());
        //对密码进行加密
        String MD5Password = MD5Util.hmacSign(user.getPassword());
        user.setPassword(MD5Password);
        Users userInfo = usersMapper.getUser(user.getEmail());
        if (userInfo==null){
            usersMapper.insertUser(user);
            return Result.ok("注册成功");
        }
        return Result.err(Result.CODE_500,"注册失败,邮箱或用户名已经存在");
    }

    /**
     * 用户登录
     * @param user
     * @return
     */
    public Result login(User user, HttpServletResponse response, HttpServletRequest request, HttpSession session) {
        //根据用户名查询用户
        Users u = usersMapper.getUserByUsername(user.getUsername());
        if(u==null || u.getStatus()==UserStatus.USER_STATE_FALSE){
            return Result.err(Result.CODE_500,"用户不存在");
        }
        if(!(u.getPassword().equals(MD5Util.hmacSign(user.getPassword())))){
            return Result.err(Result.CODE_500,"用户名或者密码错误");
        }
        // 校验验证码
        String captchaIn = user.getCaptcha();
        String captcha = stringRedisTemplate.opsForValue().get(CAPTCHA_KEY);
        if (captcha==null){
            return Result.err(Result.CODE_500,"验证码已过期");
        }
        if (captchaIn==null || !captchaIn.equals(captcha)){
            return Result.err(Result.CODE_500,"验证码输入有误");
        }
        //将密码放入到cookie中
        if (user.getRemember()){
            Cookie ck1 = new Cookie("username", user.getUsername());
            response.addCookie(ck1);
            Cookie ck2 = new Cookie("password", user.getPassword());
            response.addCookie(ck2);
            Cookie ck3 = new Cookie("remember", "true");
            response.addCookie(ck3);
        }else{
            //清除cookie
            Cookie[] cks=request.getCookies();
            if(cks !=null){
                for (Cookie c : cks) {
                    c.setMaxAge(0);
                    response.addCookie(c);
                }
            }
        }
        //这里是登录成功
        String token = tokenUtils.loginSign(u, user.getPassword());
        System.out.println("token:       n "+token);
        String tokenRedis = stringRedisTemplate.opsForValue().get(user.getUsername());
        if (!(token.equals(tokenRedis))||tokenRedis==null){
            stringRedisTemplate.opsForValue().set(user.getUsername(),token,3600,TimeUnit.SECONDS);
        }
        //登录成功并且返回token
        return Result.ok("登录成功",token);
    }

    /**
     * 用户忘记密码功能--给邮箱发送验证码
     */
    public Result sendCode(EmailVO emailVO) {
        // 1、 根据邮箱查询用户
        Users users = usersMapper.getByEmail(emailVO.getEmail());
        // 2、 没有该用户 返回邮箱未注册或者有误
        if (users == null ){
            return Result.err(Result.CODE_500,"邮箱未注册或者有误");
        }
        // 3、 查询到该用户
        // 3.1 生成验证码并保存到redis中，有效期为1分钟
        String code = RandomUtil.randomNumbers(6);
        stringRedisTemplate.opsForValue().set(EMAIL_CODE_KEY+emailVO.getEmail(),code,1, TimeUnit.MINUTES);
        // 3.2 通过邮件发送验证码
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("1486165831@qq.com"); //设置发件人
        message.setText("您的验证码为：" + code+"，有效期为1分钟"); //设置邮件内容
        message.setTo(emailVO.getEmail()); //设置收件人邮箱
        javaMailSender.send(message); //发送邮件
        // 4、 返回发送验证码成功
        return Result.ok("发送验证码成功！");
    }

    /**
     * 校验验证码
     */
    public Result verifyCode(EmailVO emailVO) {

        // 1、 先校验邮箱，防止发送验证码后更改邮箱
        Users users = usersMapper.getByEmail(emailVO.getEmail());
        // 2、 没有该用户 返回邮箱未注册或者有误
        if (users == null ){
            return Result.err(Result.CODE_500,"邮箱未注册或者有误");
        }
        // 3、 校验验证码
        String code = stringRedisTemplate.opsForValue().get(EMAIL_CODE_KEY + emailVO.getEmail());
        if (emailVO.getCode() == null || !code.equals(emailVO.getCode())){
            return Result.err(Result.CODE_500,"验证码有误");
        }
        return Result.ok("验证码正确");
    }

    /**
     * 重置密码
     */
    public Result resetPassword(EmailVO email) {
        int i = usersMapper.updatePassword(email.getEmail(), MD5Util.hmacSign(email.getNewPassword()));
        if (i>0){
            return Result.ok("修改密码成功");
        }
        return Result.err(Result.CODE_500,"修改密码失败");
    }

    /**
     * 用户登录后，通过旧密码进行密码的修改
     */
    @Override
    public Result updatePwdByOldPwd(PasswordVO passwordVO, HttpSession session) {
        String userID = (String) session.getAttribute("userID");
        String oldPassword = passwordVO.getOldPassword();
        String newPassword = passwordVO.getNewPassword();
        Users users = usersMapper.getUserByID(userID);
        if (users == null){
            return Result.err(Result.CODE_500,"用户不存在");
        }
        if (!MD5Util.hmacSign(oldPassword).equals(users.getPassword())){
            return Result.err(Result.CODE_500,"旧密码错误");
        }
        if (passwordVO.getNewPassword().equals(passwordVO.getOldPassword())){
            return Result.err(Result.CODE_500,"新密码不能与旧密码相同");
        }
        int i = usersMapper.updatePassword(users.getEmail(), MD5Util.hmacSign(newPassword));
        if (i>0){
            return Result.ok("修改密码成功");
        }
        return Result.err(Result.CODE_500,"修改密码失败");
    }

    @Override
    public Result logout(HttpServletRequest request) {
        String token = request.getHeader(CampusWall.CAMPUS_TOKEN);
        token = tokenUtils.getToken(token);
        //获取当前的用户名
        Users currentUser = tokenUtils.getCurrentUser(token);
        Boolean delete = stringRedisTemplate.delete(currentUser.getUsername());
        return Result.ok("退出成功");
    }

    @Override
    public Result getUserInfo(HttpServletRequest request) {
        try {
            // 从请求头中获取token
            String token = request.getHeader(CampusWall.CAMPUS_TOKEN);
            token = tokenUtils.getToken(token);
            
            // 从token中获取用户信息
            Users currentUser = tokenUtils.getCurrentUser(token);
            
            // 根据用户ID查询完整的用户信息
            Users userInfo = usersMapper.getUserByID(currentUser.getUserId());
            
            if (userInfo == null) {
                return Result.err(Result.CODE_500, "用户不存在");
            }
            
            // 移除敏感信息（密码）
            userInfo.setPassword(null);
            
            return Result.ok("获取用户信息成功", userInfo);
        } catch (Exception e) {
            return Result.err(Result.CODE_500, "获取用户信息失败：" + e.getMessage());
        }
    }
    /**
     * 获取验证码以及请求验证码
     */
    public Result getCaptcha() {
        // 1、 生成4位的验证码
        String captcha = RandomCaptcha.getRandomString(4);
        // 2、 先删除旧的验证码
        stringRedisTemplate.delete(CAPTCHA_KEY);
        // 3、 再存入新的验证码
        stringRedisTemplate.opsForValue().set(CAPTCHA_KEY,captcha,2,TimeUnit.MINUTES);
        // 4、 返回验证码
        return Result.ok(captcha,"验证码获取成功");
    }
}

